package core
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	import flash.utils.ByteArray;

	import mx.controls.Alert;
	import mx.core.UIComponent;
	import mx.managers.PopUpManager;

	import view.MapComponent;
	import view.ResourceView;
	import view.TileTreeWindow;

	public class MapController
	{
		public static const TILE : int = 1;
		public static const LADDER_UP : int = 2;
		public static const LADDER_DOWN : int = 3;
		public static const LADDER_MIDDLE : int = 4;


		public static const TILE_IMG : int = 1;
		public static const LADDER_IMG : int = 2;
		public static const OTHER_IMG : int = 3;


		private static var instance : MapController;
		private var scene : UIComponent;
		public const SCALE : int = 2;
		/**
		 * 当前绘制的地图元素名称
		 */
		public var currElementName : String = "";
		/**
		 * 填充层
		 */
		private var fillMiniCanvas : Sprite = new Sprite();
		private var fillMapCanvas : Sprite = new Sprite();
		/**
		 * 小地图
		 */
		private var minMapCanvas : Sprite = new Sprite();
		/**
		 * 地图层
		 */
		private var mapCanvas : Sprite = new Sprite();
		/**
		 * 地表层
		 */
		private var tileCanvas : Sprite = new Sprite();
		/**
		 * 楼梯层
		 */
		private var ladderCanvas : Sprite = new Sprite();
		/**
		 * 地图其他元素
		 */
		private var otherCanvas : Sprite = new Sprite();
		/**
		 * 网格层
		 */
		private var mapGrid : Sprite = new Sprite();
		/**
		 * 坐标
		 */
		private var mapTexts : Sprite = new Sprite();

		/**
		 * 地板，楼梯不同状态的填充颜色
		 *
		 */
		private const COLOR_TILE : int = 0xffff00;
		private const COLOR_LADDER_NORMAL : int = 0xff0000;
		private const COLOR_LADDER_DOWN : int = 0x000fff;
		private const COLOR_LADDER_UP : int = 0xff0fff;
		private const COLOR_RESET : int = 0xdddddd;
		/**
		 * 是否调整格子信息
		 */
		public var isChangNode : Boolean;
		/**
		 * 是否清理格子
		 */
		public var isClearNode : Boolean;
		/**
		 * 地图资源
		 */
		public var mapData : MapData;
		/**
		 * 绘制类型
		 * 地表
		 * 楼梯上
		 * 楼梯中
		 * 楼梯下
		 * 清除
		 */
		public var drawType : int = TILE;
		/**
		 * 图片类型
		 * 砖块
		 * 梯子
		 * 其他
		 */
		public var imageType : int;
		/**
		 * 地图元素类型
		 * 单向移动元素
		 * 双向移动元素
		 * 上下移动元素
		 */
		public var mapType : int;
		/**
		 * 背景资源
		 */
		private var minBgImag : Bitmap = new Bitmap();
		public var bigBgImag : Bitmap = new Bitmap();
		public var bgImagBytes : ByteArray;

		public var tileTreeWindow : TileTreeWindow;

		/**
		 * 历史记录
		 */
		public var histroy : Array = [];
		public const MAX_HISTROY : int = 30;

		private var currDraw : Sprite;
		private var currMinDraw : Sprite;

		public function MapController()
		{
		}

		public static function getInstance() : MapController
		{
			if(instance == null)
			{
				instance = new MapController();
				instance.init();
			}
			return instance;
		}

		public function set bitmapData(value : BitmapData) : void
		{
			minBgImag.alpha = 0.4;
			minBgImag.bitmapData = value;
			minBgImag.scaleX = 1 / SCALE;
			minBgImag.scaleY = 1 / SCALE;

			bigBgImag.bitmapData = value;
		}

		private function init() : void
		{
			bigBgImag.y = Config.tileHeight * .5;

			scene = Config.stage.scene;
			mapCanvas.addEventListener(MouseEvent.CLICK, onDrawMapElementHandler);
			mapCanvas.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
			mapCanvas.addEventListener(MouseEvent.ROLL_OUT, onMouseOutHandler);
			mapCanvas.addEventListener(MouseEvent.MOUSE_UP, onMouseOutHandler);
			mapCanvas.addEventListener(MouseEvent.MOUSE_MOVE, onUpdateStatusHandler);
			scene.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
		}

		private function onKeyDownHandler(evt : KeyboardEvent) : void
		{
			if(evt.ctrlKey && evt.keyCode == Keyboard.Z && histroy.length > 0)
			{
				var data : Object = histroy.pop();
				var row : int = data.row;
				var col : int = data.col;

				var node : Node = mapData.data[col][row];
				Config.readObject(node, data);
				this.createNodeElements(node);
			}
		}

		public function getSaveMapBitmapData() : BitmapData
		{
			var mapData : BitmapData = new BitmapData(Config.mapCols * Config.tileWidth, (Config.mapRows - 1) * Config.tileHeight, true, 0);
			var mapGrid_visible : Boolean = mapGrid.visible;
			var mapTexts_visible : Boolean = mapTexts.visible;
			setCurrDraw(null, null);
			bigBgImag.visible = true;
			mapGrid.visible = false;
			mapTexts.visible = false;
			fillMapCanvas.visible = false;
			var matrix : Matrix = new Matrix();
			matrix.ty = -Config.tileHeight * .5;
			mapData.draw(mapCanvas, matrix);
			bigBgImag.visible = false;
			fillMapCanvas.visible = true;
			mapGrid.visible = mapGrid_visible;
			mapTexts.visible = mapTexts_visible;
			return mapData;
		}

		/**
		 * 创建地图，然后绘制网格
		 *
		 */
		public function createMap() : void
		{
			childDestroy(mapCanvas);
			childDestroy(minMapCanvas);
			scene.addChild(mapCanvas);
			scene.addChild(minMapCanvas);

			minMapCanvas.x = Config.mapCols * Config.tileWidth + 20;

			var gridBox : Sprite = new Sprite();
			createGrid(gridBox, SCALE);
			minMapCanvas.addChild(fillMiniCanvas);
			minMapCanvas.addChild(minBgImag);
			minMapCanvas.addChild(gridBox);

			bigBgImag.visible = false;
			mapCanvas.addChild(fillMapCanvas);
			mapCanvas.addChild(bigBgImag);
			mapCanvas.addChild(tileCanvas);
			mapCanvas.addChild(ladderCanvas);
			mapCanvas.addChild(otherCanvas);
			mapCanvas.addChild(mapGrid);
			createGrid(mapGrid, 1);

			//设置填充区域大小
			var graphics : Graphics = fillMiniCanvas.graphics;
			graphics.clear();
			graphics.beginFill(COLOR_RESET);
			graphics.drawRect(0, 0, Config.mapCols * Config.tileWidth / SCALE, Config.mapRows * Config.tileHeight / SCALE);
			graphics.endFill();

			graphics = fillMapCanvas.graphics;
			graphics.clear();
			graphics.beginFill(COLOR_RESET);
			graphics.drawRect(0, 0, Config.mapCols * Config.tileWidth, Config.mapRows * Config.tileHeight);
			graphics.endFill();


			//创建地图数据
			mapData = new MapData();
			mapData.data = [];
			var col : int;
			var row : int;

			for(col = 0; col < Config.mapCols; col++)
			{
				mapData.data.push([]);

				for(row = 0; row < Config.mapRows; row++)
				{
					var node : Node = new Node();
					mapData.data[col][row] = node;

					var tileContainer : Sprite = new Sprite();
					tileContainer.x = col * Config.tileWidth;
					tileContainer.y = row * Config.tileHeight;
					node.tileContainer = tileContainer;

					var ladderContainer : Sprite = new Sprite();
					ladderContainer.x = col * Config.tileWidth;
					ladderContainer.y = row * Config.tileHeight;
					node.ladderContainer = ladderContainer;

					node.row = row;
					node.col = col;

					tileCanvas.addChild(tileContainer);
					ladderCanvas.addChild(ladderContainer);
				}
			}
			createTextGrid();

			addMask(mapCanvas, 0xdddddd, 0, Config.tileHeight * .5, Config.mapCols * Config.tileWidth, (Config.mapRows - 1) * Config.tileHeight);
			addMask(minMapCanvas, 0xdddddd, 0, 0, Config.mapCols * Config.tileWidth / SCALE, Config.mapRows * Config.tileHeight / SCALE);
		}

		/**
		 * 创建网格
		 * @param gridBox
		 *
		 */
		private function createGrid(gridBox : Sprite, scale : int) : void
		{
			//开始绘制网格
			var graphics : Graphics = gridBox.graphics;
			graphics.clear();
			graphics.lineStyle(1, 0xff00ff);

			for(var row : int = 0; row <= Config.mapRows; row++)
			{
				graphics.moveTo(0, row * Config.tileHeight / scale);
				graphics.lineTo(Config.mapCols * Config.tileWidth / scale, row * Config.tileHeight / scale);
			}

			for(var col : int = 0; col < Config.mapCols; col++)
			{
				graphics.moveTo(col * Config.tileWidth / scale, 0);
				graphics.lineTo(col * Config.tileWidth / scale, Config.mapRows * Config.tileHeight / scale);
			}
			graphics.endFill();
		}

		/**
		 * 为元件添加遮罩
		 * @param child
		 * @param color
		 * @param x
		 * @param y
		 * @param width
		 * @param height
		 *
		 */
		private function addMask(child : Sprite, color : int, x : Number, y : Number, width : Number, height : Number) : void
		{
			var maskShape : Shape = new Shape();
			maskShape.graphics.beginFill(color);
			maskShape.graphics.drawRect(x, y, width, height);
			maskShape.graphics.endFill();
			child.mask = maskShape;
			child.addChild(maskShape);
		}
		/**
		 * 黑色光滤镜
		 */
		public static var blackFilters : Array = [new GlowFilter(0x000000, 1, 1.5, 1.5, 255)];

		private function createTextGrid() : void
		{
			for(var col : int = 0; col < Config.mapCols; col++)
			{
				for(var row : int = 0; row < Config.mapRows; row++)
				{
					var txt : TextField = new TextField();
					mapTexts.addChild(txt);
					txt.x = col * Config.tileWidth + 20;
					txt.y = row * Config.tileHeight + 10;
					txt.mouseEnabled = false;
					txt.text = col + "-" + row;
					txt.filters = blackFilters;
					txt.textColor = 0xffffff;
				}
			}
			mapCanvas.addChild(mapTexts);
		}

		/**
		 * 根据配置文件更新数据
		 *
		 */
		public function updateMapData() : void
		{
			mapData.mapCols = Config.mapCols;
			mapData.mapRows = Config.mapRows;
			mapData.tileWidth = Config.tileWidth;
			mapData.tileHeight = Config.tileHeight;
			mapData.mapID = Config.mapID;
			mapData.resUrl = Config.resUrl;
			mapData.mapBgUrl = Config.mapBgUrl;
		}

		private function onMouseDownHandler(evt : MouseEvent) : void
		{
			mapCanvas.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler);
		}

		private function onMouseOutHandler(evt : MouseEvent) : void
		{
			mapCanvas.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler);

			if(evt.type == MouseEvent.ROLL_OUT)
			{
				setCurrDraw(null, null);
			}
		}

		private function onMouseMoveHandler(evt : MouseEvent) : void
		{
			onDrawMapElementHandler(evt);
		}

		/**
		 * 在地图上绘制地图元素
		 * @param evt
		 *
		 */
		private function onDrawMapElementHandler(evt : MouseEvent) : void
		{
			//计算出鼠标点击所在格子
			var col : int = int(mapCanvas.mouseX / Config.tileWidth);
			var row : int = int(mapCanvas.mouseY / Config.tileHeight);

			if(row < 0 || row >= Config.mapRows || col < 0 || col >= Config.mapCols)
				return;
			var node : Node = mapData.data[col][row];
			var tileContainer : Sprite = node.tileContainer;
			var ladderContainer : Sprite = node.ladderContainer;
			var mapRes : MapRes;
			var mapElement : MapElement;

			if(isChangNode)
			{
				tileTreeWindow.visible = true;
				tileTreeWindow.updateNode(node);
				return;
			}

			addHistroy(node);

			//mapCanvas.stage.focus = mapCanvas.stage;

			//根据当前选择的资源图片。。创建地图资源
			var element : Sprite = this.getDrawShape();

			if(mapType != 0 && element)
			{
				mapElement = new MapElement();
				element.x = col * Config.tileWidth;
				element.y = row * Config.tileHeight;
				mapElement.start_row = row;
				mapElement.start_col = col;
				mapElement.type = mapType;
				mapElement.setElement(element);
				mapElement.resName = currElementName;
				node.otherData.push(mapElement);
				otherCanvas.addChild(element);
			}

			//根据类型判断当前选择的属于什么资源
			switch(drawType)
			{
				//地板
				case TILE:
					//判断是空气，空气才可以改变类型。如果是楼梯就不能
					if(node.type == 0)
					{
						node.type = Config.groundType;
						node.groundHardness = 3;
					}
					break;
				//楼梯上
				case LADDER_UP:
					node.type = Config.ladderUp;
					break;
				//楼梯下
				case LADDER_DOWN:
					node.type = Config.ladderDown;
					break;
				//楼梯间
				case LADDER_MIDDLE:
					node.type = Config.ladderNormal;
					break;
			}

			if(element)
			{
				switch(imageType)
				{
					case TILE_IMG:
						mapRes = node.groundRes;
						tileContainer.addChildAt(element, 0);
						break;
					case LADDER_IMG:
						mapRes = node.ladderRes;
						ladderContainer.addChildAt(element, ladderContainer.numChildren == 0 ? 0 : 1);
						break;
					case OTHER_IMG:
						mapRes = new MapRes();
						node.res.push(mapRes);
						tileContainer.addChild(element);
						break;
				}
			}

			if(mapRes && element)
			{
				mapRes.remove();
				mapRes.setElement(element);
				mapRes.resName = currElementName;
			}

			if(isClearNode)
			{
				node.reset();
			}

			fillColorByNode(node);
		}

		private function onUpdateStatusHandler(evt : MouseEvent) : void
		{
			//计算出鼠标点击所在格子
			var col : int = int(mapCanvas.mouseX / Config.tileWidth);
			var row : int = int(mapCanvas.mouseY / Config.tileHeight);

			if(row < 0 || row >= Config.mapRows || col < 0 || col >= Config.mapCols)
				return;
			var node : Node = mapData.data[col][row];
			updateStatus(node);

			if(isClearNode || isChangNode)
			{
				setCurrDraw(null, null);
				return;
			}

			setCurrDraw(getDrawShape(), getDrawShape());

			if(currDraw)
			{
				currDraw.x = node.col * Config.tileWidth;
				currDraw.y = node.row * Config.tileHeight;
			}

			if(currDraw)
			{
				currMinDraw.x = node.col * Config.tileWidth / SCALE;
				currMinDraw.y = node.row * Config.tileHeight / SCALE;
			}
		}

		private function setCurrDraw(shape : Sprite, minShape : Sprite) : void
		{
			if(currDraw && currDraw.parent)
			{
				currDraw.parent.removeChild(currDraw);
			}
			currDraw = shape;

			if(currDraw)
			{
				mapCanvas.addChild(currDraw);
			}

			if(currMinDraw && currMinDraw.parent)
			{
				currMinDraw.parent.removeChild(currMinDraw);
			}

			currMinDraw = minShape;

			if(currMinDraw)
			{
				currMinDraw.width = currMinDraw.width / SCALE;
				currMinDraw.height = currMinDraw.height / SCALE;
				minMapCanvas.addChild(currMinDraw);
			}
		}

		/**
		 * 根据节点生成状态栏信息
		 * @param node
		 *
		 */
		public function updateStatus(node : Node) : void
		{
			var show : String = "类型:" + node.type;

			if(node.groundRes && node.groundRes.resName)
			{
				show += "地板：" + node.groundRes.resName + "  ";
			}

			if(node.ladderRes && node.ladderRes.resName)
			{
				show += "楼梯：" + node.ladderRes.resName + "  ";
			}
			show += "其他资源个数：" + node.res.length;
			Config.stage.status = show;
		}

		private function getDrawShape() : Sprite
		{
			var shape : Sprite = new Sprite();
			var color : int = 0;

			if(imageType == 0 && mapType == 0)
			{
				switch(drawType)
				{
					case TILE:
						color = COLOR_TILE;
						break;
					case LADDER_UP:
						color = COLOR_LADDER_UP;
						break;
					case LADDER_DOWN:
						color = COLOR_LADDER_DOWN;
						break;
					case LADDER_MIDDLE:
						color = COLOR_LADDER_NORMAL;
						break;
					default:
						return null;
						break;
				}
				var graphics : Graphics = shape.graphics;
				graphics.beginFill(color);
				graphics.drawRect(0, 0, Config.tileWidth, Config.tileHeight);
				graphics.endFill();
			}

			if(currElementName)
			{
				shape.addChild(Config.createComponetByName(currElementName));
			}
			shape.mouseChildren = shape.mouseEnabled = false;
			return shape;
		}

		public function fillColorByNode(node : Node) : void
		{
			var color : int = COLOR_RESET;

			switch(node.type)
			{
				case Config.groundType:
					color = COLOR_TILE;
					break;
				case Config.ladderUp:
					color = COLOR_LADDER_UP;
					break;
				case Config.ladderDown:
					color = COLOR_LADDER_DOWN;
					break;
				case Config.ladderNormal:
					color = COLOR_LADDER_NORMAL;
					break;
			}
			var graphics : Graphics = fillMiniCanvas.graphics;
			graphics.beginFill(color);
			graphics.drawRect(node.col * Config.tileWidth / SCALE, node.row * Config.tileHeight / SCALE, Config.tileWidth / SCALE, Config.tileHeight / SCALE);
			graphics.endFill();

			graphics = fillMapCanvas.graphics;
			graphics.beginFill(color);
			graphics.drawRect(node.col * Config.tileWidth, node.row * Config.tileHeight, Config.tileWidth, Config.tileHeight);
			graphics.endFill();
		}

		public function createTileWindow() : void
		{
			tileTreeWindow = PopUpManager.createPopUp(Config.stage, TileTreeWindow) as TileTreeWindow;
			tileTreeWindow.x = Config.tileWidth * Config.mapCols + 280;
			tileTreeWindow.y = 375;
		}

		/**
		 * 清除节点里面的某个类型数据
		 * @param node
		 * @param type
		 *
		 */
		private function clearMapDataRes(node : Node, type : String) : void
		{
			var len : int = node.res.length;

			for(var i : int = len - 1; i >= 0; i--)
			{
				var res : String = node.res[i];

				if(res.indexOf(type) >= 0)
					node.res.splice(i, 1);
			}
		}

		/**
		 * 根据地图数据创建地图
		 *
		 */
		public function createMapByMapData() : void
		{
			if(mapData == null)
				return;
			var len : int = mapData.data.length;

			for(var col : int = 0; col < len; col++)
			{
				for(var key : String in mapData.data[col])
				{
					var node : Node = mapData.data[col][key];
					createNodeElements(node);
				}
			}
		}

		/**
		 * 创建节点的元素
		 *
		 */
		public function createNodeElements(node : Node) : void
		{
			node.clearElements();

			if(node.groundRes)
			{
				createMapElement(node.groundRes, node.tileContainer);
			}

			if(node.ladderRes)
			{
				createMapElement(node.ladderRes, node.ladderContainer);
			}

			var mapRes : MapRes;

			for each(mapRes in node.res)
			{
				createMapElement(mapRes, node.tileContainer);
			}

			for each(mapRes in node.otherData)
			{
				createMapElement(mapRes, otherCanvas);
			}

			this.fillColorByNode(node);
		}

		/**
		 * 添加历史记录
		 * @param node
		 *
		 */
		private var oldHistroyNode : Node;

		public function addHistroy(node : Node) : void
		{
			if(oldHistroyNode && oldHistroyNode.toString() == node.toString())
			{
				return;
			}
			oldHistroyNode = node;

			if(histroy.length > MAX_HISTROY)
			{
				histroy.shift();
			}
			histroy.push(Config.clone(node));
		}

		/**
		 * 创建地图元素
		 * @param mapRes
		 * @param container
		 *
		 */
		private function createMapElement(mapRes : MapRes, container : Sprite) : void
		{
			if(mapRes.resName == "" || mapRes.resName == null)
			{
				return;
			}
			var element : DisplayObject = Config.createComponetByName(mapRes.resName) as DisplayObject;
			element.x = mapRes.offsetX;
			element.y = mapRes.offsetY;

			if(mapRes is MapElement)
			{
				element.x = int(MapElement(mapRes).start_col) * Config.tileWidth + mapRes.offsetX;
				element.y = int(MapElement(mapRes).start_row) * Config.tileHeight + mapRes.offsetY;
			}
			mapRes.setElement(element);
			container.addChild(element);
		}

		/**
		 * 是否显示网格
		 * @param value
		 *
		 */
		public function showMapGrid(value : Boolean) : void
		{
			mapGrid.visible = value;
		}

		/**
		 * 显示数字
		 *
		 */
		public function showNumGrid(value : Boolean) : void
		{
			mapTexts.visible = value;
		}

		/**
		 * 是否显示地表
		 * @param value
		 *
		 */
		public function showMapGround(value : Boolean) : void
		{
			for(var col : int = 0; col < Config.mapCols; col++)
			{
				for(var row : int = 0; row < Config.mapRows; row++)
				{
					var node : Node = mapData.data[col][row];

					if(node && node.groundRes && node.groundRes.getElement())
					{
						node.groundRes.getElement().visible = value;
					}
				}
			}
		}

		/**
		 * 是否显示楼梯
		 * @param value
		 *
		 */
		public function showLadder(value : Boolean) : void
		{
			ladderCanvas.visible = value;
		}

		/**
		 * 是否显示其他资源
		 * @param value
		 *
		 */
		public function showOtherRes(value : Boolean) : void
		{
			tileCanvas.visible = value;
		}


		public static function childDestroy(disObj : DisplayObjectContainer) : void
		{
			var num : int = disObj.numChildren;
			var child : DisplayObject;

			for(var i : int = num - 1; i >= 0; i--)
			{
				child = disObj.getChildAt(i);

				if(child == null)
					continue;

				if(child is MovieClip)
				{
					MovieClip(child).stop();
				}

				if(child is DisplayObjectContainer)
				{
					childDestroy(child as DisplayObjectContainer);
				}

				if(child.parent)
					child.parent.removeChild(child);
			}
		}
	}
}